//定义工具的类
class Tools {
    _$ = selector => document.querySelector(selector)
    //创建元素
    _c = tagName => document.createElement(tagName)
    //设定元素样式
    _s = (el, styleObj) => {
        for (let k in styleObj) {
            //对象for in 循环中的 k 表示每一个 属性：属性值 中的属性
            el.style[k] = styleObj[k]
        }
    }
}

//定义轮播图的操作核心类，内置控制轮播图的方法
class Carousel extends Tools {
    constructor() {
        //添加到当前实例化的实例上  this.属性 = 值
        super()
        //获取图片容器
        this.wrap = this._$(".wrap")
        //一张图的宽度
        this.mask = this._$("#mask")
        this.onePicWidth = this.mask.offsetWidth
        //移动到目标图片的索引
        this.picIndex = 0
        //获取箭头
        this.arrow = this._$(".arrow")
        //获取container
        this.container = this._$("#container")
        //获取左箭头
        this.leftArr = this.arrow.children[0]
        //获取右箭头
        this.rightArr = this.arrow.children[1]
        //获取指示器容器
        this.indicator = this._$(".indicator")
        //声明一个用于判断是否调用显示指示器indicator()的开关
        this.isShowIndicator = false
        //定义一个是否开启无缝轮播的开关量
        this.isCircular = false
        //根据图片数量 动态创建宽
        this._s(this.wrap,{width:this.wrap.children.length*this.onePicWidth+"px"})
        //判断自动轮播开启否
        this.isAutoPlay = false

    }
    //定义图片移动方法
    slider = () => {
        animate(this.wrap, -(this.onePicWidth * this.picIndex))
    }
    //定义鼠标事件
    bindMouseEvent = () => {
        //鼠标划入事件
        this.mask.onmouseenter = () => {
            this._s(this.arrow, { display: "block" })
            //如果是在开启自动轮播的情况下，清除定时器停止轮播
            if(this.isAutoPlay){
                clearInterval(this.interval)
            }
        }
        //鼠标移出事件
        this.container.onmouseleave = () => {
            this._s(this.arrow, { display: "none" })
            if(this.isAutoPlay){
                this.play()
            }
        }
        //左箭头点击事件
        this.leftArr.onclick = () => {
            this.prev()
        }
        //右箭头点击事件
        this.rightArr.onclick = () => {
            this.next()
        }
    }
    //为了方便调用控制自动轮播而细化出两个方法
    //上一张图
    prev = () => {
        //控制picIndex--
        this.picIndex--
        if(this.picIndex<0){
            if(this.isCircular){
                this._s(this.wrap,{left:-(this.wrap.children.length-1)*this.onePicWidth+"px"})
                this.picIndex=this.wrap.children.length-2
            }else{
                this.picIndex=this.wrap.children.length-1
            }
        }
        this.slider()
        //先判断指示器indicator是否显示，显示了 再调用高亮函数
        if(this.isShowIndicator){
            this.indicatorActive()
        }
    }
    //下一张图
    next = () => {
        //控制picIndex++
        this.picIndex++
        //有缝轮播
        if(this.picIndex==this.wrap.children.length){
            if(this.isCircular){
                //手动调整warp位置，放到left=0位置
                this._s(this.wrap,{left:0})
                //将picIndex赋值1
                this.picIndex=1
            }else{
                this.picIndex=0
            }
        }
        this.slider()
        if(this.isShowIndicator){
            this.indicatorActive()
        }
    }
    //控制指示器动态个数显示
    showIndicator() {
        //开局先改变开关变量的值,表示调用了
        this.isShowIndicator=true
        //根据图片数量动态添加指示器个数
        let len = this.wrap.children
        //循环创建指示器
        for (let i = 0; i < len.length; i++) {
            //创建一个li节点
            let li = this._c("li")
            //在创建的节点里添加标号
            li.innerText = i + 1
            //添加到显示器的容器indicator里
            this.indicator.appendChild(li)
        }
        //事件委托父元素注册指示器时间
        this.indicator.addEventListener("click", (e) => {
            e = e || window.event
            if (e.target.localName == "li") {
                //点击对应的指示器，修改picIndex的值，调用slider实现点击滑动
                this.picIndex = e.target.innerText - 1
                if(this.isShowIndicator){
                    this.indicatorActive()
                }
                this.slider()
            }
        })
        //让显示器的容器显示
        // this._s(this.indicator,{display:"block"})
        //在首次控制显示器动态个数显示的时候先高亮显示
        if(this.isShowIndicator){
            this.indicatorActive()
        }
    }
    //指示器选中高亮激活方法
    indicatorActive(){
        //在indicatorActive被调用后 获取点击元素的索引值
        let indicatorIndex = this.picIndex
        //获得点击的指示器
        //去掉所有指示器的active类名，给所点击的指示器添加active类名
        let indicators = this.indicator.children
        //借用上面的循环给每个li添加点击事件，此处只写排它即可
        for(let i = 0;i<indicators.length;i++){
            indicators[i].className=""
        }
        //判断轮播方法
        if(this.isCircular && indicatorIndex==this.wrap.children.length-1){
            indicatorIndex=0
        }
        indicators[indicatorIndex].className="active"
    }
    //控制无缝轮播方法
    circular(){
        this.isCircular=true
        //clone第一个图片放到最后
        let firstNode = this.wrap.children[0]
        let lastNode = firstNode.cloneNode(true)
        this.wrap.appendChild(lastNode)
        //重新计算wrap的宽
        this._s(this.wrap,{width:this.wrap.children.length*this.onePicWidth+"px"})
    }
    //定义一个自动播放方法
    play(delay = 1000){
        // this.isAutoPlay=true
        this.interval = setInterval(()=>{
            this.next()
        },delay)
    }
    autoPlay(delay){
        this.isAutoPlay=true
        //在这里先调用一次，避免获取焦点之前 不进行轮播
        this.play(delay)
        window.onfocus = () =>{
            this.play(delay)
        }
        window.onblur = () =>{
            if(this.interval){
                clearInterval(this.interval)
            }
        }
    }
}
//实例化 Carousel
let c = new Carousel()
// console.log(c);
c.bindMouseEvent()
c.showIndicator()
c.circular()
c.autoPlay()
